package com.supermap.dataservice.websocket;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import com.alibaba.fastjson.JSONObject;
import com.supermap.dataservice.project.service.ExpertConsultationServiceImpl;
import com.supermap.dataservice.util.DateUtil;
import com.supermap.dataservice.util.JSONUtils;
import com.supermap.dubbo.api.product.entity.ExpertConsultation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**  
 * @Description: TODO
 * @author zhoujian
 * @date 2019-7-17
 * @version V1.0 
 */
@ServerEndpoint(value="/websocket/{user}")
@Component
public class WebSocketService
{
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    //与某个客户端的连接会话，需要通过它来给客户端发送数据  
    private Session session;

    private static ExpertConsultationServiceImpl expertConsultationServiceImpl;

    // 注入的时候，给类的 service 注入
    @Autowired
    public void setChatService(ExpertConsultationServiceImpl expertConsultationServiceImpl) {
        WebSocketService.expertConsultationServiceImpl = expertConsultationServiceImpl;
    }

    
    public static Map<Integer, CopyOnWriteArraySet<WebSocketService>> webSocketSet = new HashMap<>();
   
    private Integer roomId;
    private String userName;

    
    /** 
     * 连接建立成功调用的方法 
     */  
    @OnOpen  
    public void onOpen(@PathParam("user")String user ,Session session) {
        Integer roomId = Integer.valueOf(user.split("-")[0]);
        String userName = user.split("-")[1];
        /**
         * 1. 验证房间是否存在
         * 2. 验证该用户是否存在于房间中
         *  验证成功之后才能进入
         */
        JSONUtils jsonUtils = expertConsultationServiceImpl.selectByPrimaryKey(roomId);
        if(jsonUtils.getCountSum() > 0 )
        {
            //房间存在
            //判断用户是否存在于房间
            ExpertConsultation expertConsultation = (ExpertConsultation) jsonUtils.getData();
            String joinUserNames = expertConsultation.getJoinUserName();
            if (joinUserNames.contains(userName))
           {
               this.session = session;
               this.roomId = roomId;
               this.userName = userName;
               CopyOnWriteArraySet<WebSocketService> friendArraySet = webSocketSet.get(roomId);
               if (friendArraySet == null)
               {
                   synchronized (this)
                   {
                       if (!webSocketSet.containsKey(roomId))
                       {
                           friendArraySet = new CopyOnWriteArraySet<WebSocketService>();
                           webSocketSet.put(roomId, friendArraySet);
                       }
                   }
               }else {
                   Message msg = new Message();
                   msg.setUserName("系统");
                   msg.setCreateTime(DateUtil.DateToString(new Date() , "yyyy-MM-dd HH:mm:ss"));
                   msg.setMessage(this.userName+"上线");
                   broadcast(JSONObject.toJSONString(msg), friendArraySet);
               }
               friendArraySet.add(this);
           }else
            {
                return;
            }
        }else
        {
            return;
        }
    }
   
    /** 
     * 连接关闭调用的方法 
     */  
    @OnClose  
    public void onClose() {  
        CopyOnWriteArraySet<WebSocketService> friendArraySet = webSocketSet.get(roomId);
        if (friendArraySet != null)
		{
        	//首先移除自己
        	friendArraySet.remove(this);
        	//想起他群里用户发出用户下线通知
            Message msg = new Message();
            msg.setUserName("系统");
            msg.setCreateTime(DateUtil.DateToString(new Date() , "yyyy-MM-dd HH:mm:ss"));
            msg.setMessage(this.userName+"下线");
			broadcast(JSONObject.toJSONString(msg), friendArraySet);
		}
    }
   
    /** 
     * 收到客户端消息后调用的方法 
     * 
     * @param message 客户端发送过来的消息*/  
    @OnMessage  
    public void onMessage(String message, Session session) {
        if (this.roomId == null || this.userName == null)
        {
            return;
        }
        /**
         *  每发送一条消息都要记录到聊天记录文件中
         *  封装消息格式
         *  张三  2019-07-24 15:20:20
         *      hello
         */
        //创建详细实体
        Message msg = new Message();
        msg.setUserName(this.userName);
        msg.setCreateTime(DateUtil.DateToString(new Date() , "yyyy-MM-dd HH:mm:ss"));
        msg.setMessage(message);
//        String newMessage = this.userName + " " + DateUtil.DateToString(new Date() , "yyyy-MM-dd HH:mm:ss") + "\n\t" + message;
        expertConsultationServiceImpl.saveHistoryChat(this.roomId , JSONObject.toJSONString(msg));
        //记录到聊天记录文件中
        CopyOnWriteArraySet<WebSocketService> copyOnWriteArraySet = webSocketSet.get(roomId);
        if (copyOnWriteArraySet != null)
		{
        	//群发消息  
        	broadcast(JSONObject.toJSONString(msg), copyOnWriteArraySet);
		}
    }
   
    /** 
     * 发生错误时调用 
     * 
     */  
    @OnError  
    public void onError(Session session, Throwable error) {  
        System.out.println("发生错误");  
        error.printStackTrace();  
    }
    
    /** 
     * 发送消息
     * */  
    public  void broadcast(String message , CopyOnWriteArraySet<WebSocketService> copyOnWriteArraySet){
        for (WebSocketService item : copyOnWriteArraySet) {  
               try
			{
            	   item.session.getBasicRemote().sendText(message);
			}
			catch (IOException e)
			{
				e.printStackTrace();
				logger.error(e.getMessage());
			}  
        }  
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}
